<?php
/**
 * @author Sergey Dostovalov
 */
require_once 'MarcRecord.php';
require_once 'MarcConstants.php';
/**
 * @author Sergey Dostovalov
 * @example
 * $reader = new MarcReader();
 * $reader->sourceFile('test2.mrc');
 * while($record = $reader->next()){
 *      echo $record->__toString();
 * }
 */
class MarcReader {
    const SOURCE_FILE = 1;
    const SOURSE_RAW = 2;
    
    private $records = array();
    private $recordsCount = 0;
    private $nextRecord = -1; //pointer to record
    private $rawRecords;
    private $rawRecordsArray;
    private $rawEncoding  = 'UTF-8';
    /**
     *
     * @param string $sourse $raw string of marc or name of marc file
     * @param int $sourceType
     * @param string $rawEncoding
     * @exception Exception
     */
    public function  __construct($sourse, $sourceType, $rawEncoding = 'UTF-8') 
    {
        $this->rawEncoding = $rawEncoding;
        if ($sourceType === self::SOURCE_FILE){
            try{
                $this->sourceFile($sourse, $this->rawEncoding);
            }
            catch(Exception $e){
                throw $e;
            }
        }
        
        if ($sourceType === self::SOURSE_RAW){
            $this->sourceRaw($sourse, $this->rawEncoding);
        }
    }
    public function getRawRecords(){
        return $this->rawRecords;
    }
    /**
     *
     * @return int records count
     */
    public function getRecordsCount(){
        $this->init();
        return $this->recordsCount;
    }
    /**
     *
     * @param int $index of record
     */
    public function getByIndex($index){
        $this->init();
        return $this->records[$index];
    }
    /**
     * Get next record
     * @return MarcRecord
     * @return null
     */
    public function next(){
        $this->init();
        ++$this->nextRecord; //it's faster
        if ($this->nextRecord === $this->recordsCount) return null;
        return new MarcRecord($this->rawRecordsArray[$this->nextRecord].MarcConstants::END_OF_RECORD, $this->rawEncoding);
    }
    /**
     * Get previous record
     * @return MarcRecord
     * @return null
     */
    public function previous(){
        $this->init();
        --$this->nextRecord;
        if ($this->nextRecord === -1) return null;
        return new MarcRecord($this->rawRecordsArray[$this->nextRecord].MarcConstants::END_OF_RECORD, $this->rawEncoding);
    }
    /**
     * @param string $filename path to marc file
     * @param string $rawEncoding encoding of marc raw
     * @exception Exception
     */
    public function sourceFile($filename, $rawEncoding = 'UTF-8')
    {
        if (!file_exists($filename) or !is_file($filename)){
            throw new Exception('File '.$filename.' not exsist');
        }
        if(!$file = @fopen($filename, 'rb')){
            throw new Exception('File '.$filename.' can\'t read');
        }
        if(!$this->rawRecords = fread($file, filesize($filename))){
            throw new Exception('File '.$filename.' not readed');
        }
        //$marcFile->fpassthru();
    }
     /**
     * @param string $raw raw marc string
     * @param string $rawEncoding encoding of marc raw
     */
    public function sourceRaw(&$raw, $rawEncoding = 'UTF-8')
    {
        
        $this->rawRecordsArray = explode(MarcConstants::END_OF_RECORD, $raw);
        unset($this->rawRecordsArray[count($this->rawRecordsArray)-1]); //last element of $records empty string
        $this->recordsCount = count($this->rawRecordsArray);
    }
    private function init(){
        if (!$this->recordsCount)
            $this->sourceRaw($this->rawRecords, $this->rawEncoding);
    }
}
?>
